using System;
using System.Collections.Generic;
using Tycho.Parser.Tokens;

namespace Tycho.Parser.Peg {
    public abstract class MemoisedProduction<Context, Result> where Result : MemoisedParseResult<Context> {
        private readonly Dictionary<int, Result> MemoisedResults;
        public Func<Term, Context, Context> Action;

        protected MemoisedProduction () : this (null) {
        }

        protected MemoisedProduction (Func<Term, Context, Context> action) {
            Action = action;
            MemoisedResults = new Dictionary<int, Result> ();
        }

        public Result Parse (Token[] tokens, int index, Context context) {
            Result result;
            if (!MemoisedResults.TryGetValue (index, out result)) {
                result = ReallyParse (tokens, index, context);

                if (Action != null && result != null) {
                    result.Context = Action (result.Term, result.Context);
                }

                MemoisedResults.Add (index, result);
            }

            return result;
        }

        protected abstract Result ReallyParse (Token[] tokens, int index, Context context);
    }
}